package com.liruo.treasureattic.authserver.config;

import com.liruo.treasureattic.authserver.component.JwtTokenEnhancer;
import com.liruo.treasureattic.authserver.service.UserDetailsServiceImpl;
import com.liruo.treasureattic.common.config.properties.JwtProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.*;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Arrays;

/**
 * @Author:liruo
 * @Date:2022-10-09-22:07:49
 * @Desc
 */
//@Configuration
//@EnableAuthorizationServer
public class AuthenticationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Resource
    private DataSource dataSource;
    @Resource
    private UserDetailsServiceImpl userDetailsService;
    @Resource
    private AuthenticationManager authenticationManager;
    @Resource
    private JwtTokenEnhancer jwtTokenEnhancer;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private TokenStore tokenStore;
    @Resource
    private JwtAccessTokenConverter jwtAccessTokenConverter;

    @Resource
    private JwtProperties jwtProperties;

    @Resource
    private ClientDetailsService clientDetailsService;

    @Bean
    public AuthorizationServerTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        //获取client信息
        defaultTokenServices.setClientDetailsService(clientDetailsService);
        //允许刷新token
        defaultTokenServices.setSupportRefreshToken(true);

        //token增强
        defaultTokenServices.setTokenStore(tokenStore);
        defaultTokenServices.setAccessTokenValiditySeconds(
                jwtProperties.getAccessTokenValiditySeconds());
        defaultTokenServices.setRefreshTokenValiditySeconds(
                jwtProperties.getRefreshTokenValiditySeconds()
        );
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(
                jwtTokenEnhancer,jwtAccessTokenConverter));
        defaultTokenServices.setTokenEnhancer(tokenEnhancerChain);

        return defaultTokenServices;
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        JdbcClientDetailsService jdbcds = new JdbcClientDetailsService(dataSource);
        jdbcds.setPasswordEncoder(passwordEncoder);
        //给Provider设置了UserDetailService
        clients.withClientDetails(jdbcds);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .authorizationCodeServices(new JdbcAuthorizationCodeServices(dataSource))
                .userDetailsService(userDetailsService)
                .tokenServices(tokenServices())
//                .exceptionTranslator(new DefaultWebResponseExceptionTranslator())
                .allowedTokenEndpointRequestMethods(HttpMethod.POST)
//                oauth2的token认证接口/oauth/token、/oauth/check_token、/oauth/authorize
                .pathMapping("/oauth/token","/auth/token")
                .pathMapping("/oauth/check_token","/auth/check_token")
        ;

    }


    @Override
    public void configure(AuthorizationServerSecurityConfigurer server) throws Exception {
        server.tokenKeyAccess("permitAll()")///oauth/token_key
                .checkTokenAccess("permitAll()")///oauth/check_token
                .allowFormAuthenticationForClients()
//                .accessDeniedHandler()
        ;

    }

}
